import { WinstonModule, utilities } from 'nest-winston';
import { format, transports } from 'winston';
import * as wdrf from 'winston-daily-rotate-file';
import path from 'node:path';
import { DateUtils } from 'src/utils/date.util';

export function customLogger(configService) {
  //初始化从配置中获取权限服务认证相关的配置
  // #日志日志保留的天数，即可保留个数的，
  const maxFiles = configService.get('LOG_MAX_FILES');
  // #日志大小，10M
  const maxSize = configService.get('LOG_MAX_SIZE');
  // #日子生成路径
  const dirName = configService.get('LOG_DIR_NAME');
  // #日志名称
  // =ide-aggregation-server
  const fileName = configService.get('LOG_FILE_NAME');
  // #日志级别error,warn,info,http,verbose,debug,silly
  // =info
  const level = configService.get('LOG_LEVEL');
  const isZip = configService.get('LOG_ZIP');

  let transport;
  let exceptionHandlers;
  const consoleTransport = new transports.Console({
    level: level,
    format: format.combine(
      format.timestamp(),
      format.ms(),
      utilities.format.nestLike('YMServer', {
        prettyPrint: true,
        colors: true,
        appName: true,
        processId: false,
      }),
    ),
  });

  const myFormat = format.printf(
    ({ level, ms, timestamp, message, context, stack, metadata }) => {
      level = level.toLocaleUpperCase();
      if (stack) {
        if (message) {
          return `${timestamp}${level} main ${stack} - ${message} : ${ms}`;
        } else {
          metadata = JSON.stringify(metadata);
          return `${timestamp}${level} main ${stack} - ${metadata} : ${ms}`;
        }
      } else {
        if (message) {
          return `${timestamp}${level} main ${context} - ${message} : ${ms}`;
        } else {
          metadata = JSON.stringify(metadata);
          return `${timestamp}${level} main ${context} - ${metadata} : ${ms}`;
        }
      }
    },
  );

  const fileDailyRotateTransport = new wdrf({
    level: level,
    filename: `${fileName}-%DATE%`,
    dirname: `${dirName}`,
    frequency: '#D',
    // datePattern: 'DD',
    zippedArchive: isZip == 'true' ? true : false,
    format: format.combine(
      format.timestamp({
        format: () =>
          DateUtils.getDateFormatSymbols('YYYY-MM-DD [at] HH:mm:ss z'),
      }),
      format.ms(),
      format.metadata({
        fillExcept: ['ms', 'timestamp', 'message', 'context', 'level', 'stack'],
      }),
      myFormat,
    ),
    maxFiles: maxFiles,
    maxSize: maxSize,
    auditFile: `${dirName}/${fileName}.json`,
    extension: '.log',
  });

  if (process.env.NODE_ENV != 'production') {
    //开发环境，日志输出到控制台
    transport = [consoleTransport];
    exceptionHandlers = [];
  } else {
    //生产环境，日志输出到文件
    transport = [fileDailyRotateTransport];
    exceptionHandlers = [
      new transports.File({ filename: 'log/unkown-exception.log' }),
    ];
  }
  const injectLogger = WinstonModule.createLogger({
    level: level,
    transports: transport,
    exceptionHandlers,
    exitOnError: false,
  });

  return injectLogger;
}
const stackMethodIndex = 2;
const stackLineIndex = 2;
export function getLogContext() {
  const stack = new Error().stack.split('at ');
  let logMethodDetails = stack[stackMethodIndex].trim();
  const pos = logMethodDetails ? logMethodDetails.indexOf(' ') : -1;
  if (pos > 0) {
    const aPos = logMethodDetails.indexOf('<anonymous>');
    let logMethodDetailsEx = '';
    if (aPos > 0 && aPos < pos) {
      logMethodDetailsEx = logMethodDetails.substring(
        stack[stackLineIndex].lastIndexOf(path.sep) + 1,
        stack[stackLineIndex].lastIndexOf('.'),
      );
    }
    logMethodDetails = logMethodDetails.substring(0, pos) + logMethodDetailsEx;
  }

  const logLine = stack[stackLineIndex].substring(
    stack[stackLineIndex].lastIndexOf(
      ':',
      stack[stackLineIndex].lastIndexOf(':') - 1,
    ) + 1,
    stack[stackLineIndex].lastIndexOf(':'),
  );
  logMethodDetails = logMethodDetails.replace('.', ' ' + logLine + ' ');
  return logMethodDetails;
}
